package sk.uniza.fri.cerviix.server.network;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import sk.uniza.fri.cerviix.server.Server;

public class NetworkManager
{	
	private int port = 19191;
	
	private Set<Client> clients = new HashSet<Client>();
	private Queue<ClientMessage> clientMessages = new LinkedList<ClientMessage>();
	
	private ClientListener clientListener;
	
	public NetworkManager()
	{
		clientListener = new ClientListener();
		clientListener.start();
	}
	
	@Override
	protected void finalize() throws Throwable
	{
		super.finalize();
		
		clientListener.interrupt();
		
		clients.clear();
	}
	
	private synchronized void addClient(Client client)
	{
		clients.add(client);
	}
	
	synchronized void removeClient(Client client)
	{
		Server.log.info("Removing client from clients list.");

		client.getPlayer().removeClient();
		clients.remove(client);
		
		Server.log.info(String.format("Clients count: %d", clients.size()));
	}
	
	public synchronized void receive(ClientMessage message)
	{
		clientMessages.add(message);
	}
	
	public synchronized boolean hasMessage()
	{
		return !clientMessages.isEmpty();
	}
	
	public synchronized ClientMessage getMessage()
	{
		return clientMessages.remove();
	}

	private class ClientListener extends Thread
	{
		private ServerSocket serverSocket;
		
		@Override
		public void run()
		{
			try
			{
				Server.log.info("ClientListener thread running.");
				
				serverSocket = new ServerSocket(port);
				
				Socket socket;
				
				do
				{
					try
					{
						Server.log.info("Waiting for client...");
						
						socket = serverSocket.accept();
						
						Server.log.info(String.format("Accepted connection from: %s", socket.getInetAddress()));
						
						addClient(new Client(NetworkManager.this, socket));
					}
					catch (IOException e)
					{
						Server.log.warning("ClientListener failed to accept connection.");
					}
				}
				while (!isInterrupted());
			}
			catch (IOException e)
			{
				Server.log.severe("Can't create ServerSocket at port " + port);
			}
			
			Server.log.info("ClientListener thread stopped.");
		}
		
		@Override
		public void interrupt()
		{
			super.interrupt();
			
			try
			{
				serverSocket.close();
			}
			catch (IOException e)
			{
				Server.log.warning("Can't close ServerSocket.");
			}
		}
	}
}
